home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
Xprof
/
xprof
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
13KB
|
452 lines
/*==================================================================
* File : main.c
* Package: Xprof
*
* Author : Aloke Gupta.
*
* (C) Copyright 1992, Aloke Gupta.
*==================================================================*/
/*
* main.c: Main function definitions
* Functions:
* 1. main(int argc, char **argv)
* 2. process_client(char *string, GlobalStats gstats)
* 3. process_server(char *string, GlobalStats gstats)
* 4. print_stats(FILE *fp)
* 5. process_stats(FILE *fp,long min, long max, long *distbn, Grain grain,
* long maxbuckets, StatsType statstype)
* 6. Signal handlers defined by ONSIGNAL(function, string, terminate)
* 7. t_search(char *string, char *token)
*/
static char copyright[] =
"@(#) Copyright (c) 1992 Aloke Gupta.\n\
All rights reserved.\n";
#define VERSION "1.01"
static char *xprof_version = VERSION;
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include<sys/time.h>
#include "common.h"
void set_net_latency( /* double */);
void set_net_speed ( /* double */);
#define FILENAMESIZE 128
/*
* The following are signal handlers defined at the end of this file
*/
void onhangup();
void onintr();
void onquit();
void onfpe();
void onbus();
void onsegv();
void onxcpu();
int debuglevel = 0;
int verboselevel = 2;
int trapsignal = TRUE; /* Trap signals ? */
Boolean profileflag = FALSE; /* This flag should be set only if a parameters
file is specified on the command line */
long _LINE_NUM = 0; /* The current line number */
GlobalStats globalstats;
Usage(prog_name, badfield)
char *prog_name;
char *badfield;
{
if (badfield != NULL)
fprintf(stderr,"\n\t** Unknown option: \"%s\" **\n",badfield);
fprintf(stderr, " Usage: %-8s ", prog_name);
fprintf(stderr, "-d<debuglevel> ");
fprintf(stderr, "-v<verboselevel> ");
fprintf(stderr, "-p<perffile>");
fprintf(stderr, "\n ");
fprintf(stderr, "-b<num_buckets> ");
fprintf(stderr, "-s<trapsignal> ");
fprintf(stderr, "\n ");
fprintf(stderr, "-S<Net Speed (Bytes/s> ");
fprintf(stderr, "-L<Net Latency (ms)> ");
fprintf(stderr, "[filename]\n\n");
exit(1);
}
main(argc,argv)
int argc;
char *argv[];
{
char in_string[MAXSTRINGSIZE];
char *str_ptr;
int i;
char filename[FILENAMESIZE];
FILE *fp=stdin; /* File pointer to the input file */
char perffile[FILENAMESIZE];
FILE *pp;
/*
* Process the command line arguments
*/
for (i = 1; i < argc; i++) {
if (argv[i][0] == '-') { /* Argument is a flag */
switch(argv[i][1]) {
case 'b':
if (strlen(&argv[i][1]) == 1)
MAXBUCKETS_SIZE = 4096;
else MAXBUCKETS_SIZE = atoi(&argv[i][2]);
break;
case 'd': /* Set the debug level */
if (strlen(&argv[i][1]) == 1)
debuglevel = 1;
else debuglevel = atoi(&argv[i][2]);
break;
case 'p':
strcpy(perffile, &argv[i][2]);
if ((pp = fopen(perffile,"r")) == NULL)
fprintf(stderr,"Error: Can't open initialization file:%s\n"
,perffile);
else {
parse_parameters(pp);
init_profile();
profileflag = TRUE; /* Generate profile */
}
break;
case 's': /* Trap signals ?*/
if (strlen(&argv[i][1]) == 1)
trapsignal = TRUE;
else {
int flag = atoi(&argv[i][2]);
if (flag == 0) trapsignal = FALSE;
else trapsignal = TRUE;
}
break;
case 'v': /* Set the verbosity level */
if (strlen(&argv[i][1]) == 1)
verboselevel = 1;
else verboselevel = atoi(&argv[i][2]);
break;
case 'S': /* Set the network speed */
if (strlen(&argv[i][1]) >= 1)
set_net_speed ((double) atof(&argv[i][2]) );
break;
case 'L': /* Set the network latency */
if (strlen(&argv[i][1]) >= 1)
set_net_latency((double) atof(&argv[i][2]) );
break;
default:
Usage(argv[0], argv[i]);
break;
}
}
else { /* Assume that argument is a filename */
strcpy(filename, argv[i]);
if (fp == stdin) { /* Has fp been initialized already ?*/
if ((fp = fopen(filename,"r")) == NULL) {
fprintf(stderr,"Error: Can't open input file: %s\n",filename);
exit(1);
}
}
else Usage(argv[0], filename);
}
}
{
char hostname[128];
struct timeval tp;
struct timezone tzp;
gethostname (hostname, 128);
printf("\"%s\", version %s running on %s.\n",
argv[0], xprof_version, hostname);
gettimeofday(&tp, &tzp);
printf("Date: %s\n", ctime (&tp.tv_sec));
}
if (fp == stdin) printf("** Input accepted from stdin **\n");
/*
* Set up the signal handlers.
*/
if (trapsignal == TRUE) {
signal(SIGHUP, onhangup);
signal(SIGINT, onintr);
signal(SIGQUIT, onquit);
signal(SIGFPE, onfpe);
signal(SIGBUS, onbus);
signal(SIGSEGV, onsegv);
signal(SIGXCPU, onxcpu);
}
/* Main string processing loop */
while ( fgets(in_string, MAXSTRINGSIZE, fp) != NULL) {
_LINE_NUM++;
if (strstr(in_string,"Client ") != NULL) {
if (debuglevel >= 1)
printf("%s",in_string);
process_client(in_string, &globalstats);
}
else if ((str_ptr = strstr(in_string,"REQUEST")) != NULL) {
if (debuglevel >= 1)
printf("%s",in_string);
process_request(fp, str_ptr, &globalstats);
}
else if (strstr(in_string,"<-- X11 Server") != NULL) {
if (debuglevel >= 1)
printf("%s",in_string);
process_server(in_string, &globalstats);
}
else if ((str_ptr = strstr(in_string,"REPLY")) != NULL) {
if (debuglevel >= 1)
printf("%s",in_string);
process_reply(fp, str_ptr, &globalstats);
}
else if ((str_ptr = strstr(in_string,"EVENT")) != NULL) {
if (debuglevel >= 1)
printf("%s",in_string);
process_event(fp, str_ptr, &globalstats);
}
else if ((str_ptr = strstr(in_string,"ERROR")) != NULL) {
if (debuglevel >= 1)
printf("%s",in_string);
process_error(fp, str_ptr, &globalstats);
}
}
/* Print out the statistics collected before exiting */
print_stats(stdout);
return(0);
}
/* Process the line corresponding to a message from the client
* The format of the line is:
* <timestamp> Client [Client number] --> <Num_bytes> bytes
*
* The Client number field is optional
*/
process_client(string, gstats)
char *string;
GlobalStats *gstats;
{
float time; /* The time stamp is in the form xx.yy seconds*/
char junk1[80],junk2[80],junk3[80],junk4[80];
int client_num; /* This is ignored in the current program */
unsigned num_bytes=0;
int i;
i=sscanf(string,"%f %s %s %d %s %d %s", &time, junk1, junk2,
&client_num, junk3, &num_bytes, junk4);
if (i != 7) {
i=sscanf(string,"%f %s %s %s %d %s", &time, junk1, junk2,
junk3, &num_bytes, junk4);
if (i !=6) return ;
}
/*
* Now update the global structures for the client
*/
gstats->last_time = gstats->current_time;
gstats->current_time = (long) (time * 1000);
gstats->client_bytes += num_bytes;
return;
}
/* Process the line corresponding to a message from the server
* The format of the line is:
*
* <timestamp> <Num_bytes> bytes <-- X11 Server
*
*/
process_server(string, gstats)
char *string;
GlobalStats *gstats;
{
float time; /* The time stamp is in the form xx.yy seconds*/
char junk1[80], junk2[80], junk3[80], junk4[80];
unsigned num_bytes=0;
int i;
i = sscanf(string,"%f %s %d %s %s %s", &time,junk1,&num_bytes,
junk2, junk3, junk4);
if (i < 6) return;
/*
* Now update the global structures for the server
*/
gstats->last_time = gstats->current_time;
gstats->current_time = (long) (time * 1000);
gstats->server_bytes += num_bytes;
return;
}
/*
* print_stats(): Final printout function.
* It consults the global variable "globalstats" It is not passed any
* arguments because it may be called by the interrupt service routine.
*/
print_stats(fp)
FILE *fp;
{
fprintf(fp,"Final line number: %d\n",_LINE_NUM);
fprintf(fp,"Final time stamp : %.2f Seconds\n",
(float) globalstats.current_time / 1000.0);
fprintf(fp,"Messages transferred (In Bytes):\n");
fprintf(fp," Client Server Requests Replies Events Errors");
fprintf(fp,"\n%10lu %10lu %10lu %10lu %10lu %10lu\n",
globalstats.client_bytes, globalstats.server_bytes,
globalstats.request_bytes, globalstats.reply_bytes,
globalstats.event_bytes, globalstats.error_bytes);
print_request_stats(fp);
print_reply_stats(fp);
print_event_stats(fp);
print_error_stats(fp);
if (profileflag) print_profile_stats(fp);
}
/*
* Print out the statistics of a distribution consisting of maxbuckets buckets
*/
process_stats(fp, min, max, distbn, grain, maxbuckets, statstype)
FILE *fp;
long min;
long max;
long distbn[];
Grain grain;
long maxbuckets;
StatsType statstype;
{
long number=0; /* Total number of data points. This may be different
from the number of corresponding messages.*/
double mean=0.0, variance=0.0, std_dev=0.0;
long median=0;
long mode=0;
long mode_freq=0;
long n=0;
double sum=0.0, sum_sq=0.0;
double tmp;
int i;
long datapoint;
/* Collect the total number of data points */
for (i = 0; i < maxbuckets; i++)
number += distbn[i];
/* Collect the sums, sum of squares, mode, and median */
for (i = 0; i < maxbuckets; i++) {
if (statstype == LOG2) datapoint = (long) myexp2(i);
else datapoint = i;
n += distbn[i];
tmp = (double) distbn[i] * datapoint * (double) grain;
sum += (double) tmp;
sum_sq+= (double) tmp * datapoint * (double) grain;
if (distbn[i] > mode_freq) {
mode = datapoint;
mode_freq = distbn[i];
}
if (n <= (number / 2))
median = datapoint;
}
if (number > 0) {
mean = (double) sum / (double) number;
variance = (double) (sum_sq / (double) number) - (mean * mean);
std_dev = (double) sqrt(variance);
}
fprintf(fp,"%-15s ","");
fprintf(fp,"%6s %15s %7s %7s %10s %10s\n", "Number", "Range ",
"Mode", "Median", "Mean", "Std. Dev.");
fprintf(fp,"%-15s ", "(All points)");
fprintf(fp,"%6ld %7ld-%-7ld %7ld %7ld %10.2f %10.2f\n",
number, min *(long) grain, max *(long) grain, mode * (long) grain,
median * (long) grain, mean, std_dev);
/*
* Now print out the statistics for all cases except zero interarrival time
* The same sum and sum_sq can be recycled, since it has not accumalated the
* zero case anyway !!
*/
mean = variance = std_dev = 0.0;
n = median = mode = mode_freq = 0;
min = max;
/* Collect the sums and the sum of squares */
number -= distbn[0];
if (number > 0) {
for (i = 1; i < maxbuckets; i++) {
if (statstype == LOG2) datapoint = (long) myexp2(i);
else datapoint = i;
if (distbn[i] > 0) {
n += distbn[i];
if (min > datapoint) min = datapoint;
}
if (distbn[i] > mode_freq) {
mode = datapoint;
mode_freq = distbn[i];
}
if (n <= (number / 2))
median = datapoint;
}
mean = (double) sum / (double) number;
variance = (double) (sum_sq / (double) number) - (mean * mean);
std_dev = (double) sqrt(variance);
fprintf(fp,"%-15s ", "(Zeros removed)");
fprintf(fp,"%6ld %7ld-%-7ld %7ld %7ld %10.2f %10.2f\n",
number, min * (long) grain, max * (long) grain,
mode * (long) grain, median * (long) grain, mean, std_dev);
}
}
/* t_search
Look for existence of token string in the initial position of another string
Returns 1 on success, 0 otherwise.
*/
int t_search(string, token)
char *string, *token;
{
while (*token) {
if ((*token != *string) || !(*string))
return (0); /* Return if there is a mismatch or we run out of
characters in the string */
token ++; string ++;
}
return (1); /* Succesful return */
}
/*
* Signal handler routines are defined here
* In order to force a printout AND continue execution execute the command
* kill -1 <process-number> from the shell.
*/
#define ONSIGNAL(function, signame, terminate) void function() {\
sighandler(signame, terminate); \
}
ONSIGNAL(onhangup, "Hangup", FALSE);
ONSIGNAL(onintr, "Interrupt", TRUE);
ONSIGNAL(onquit, "Quit", TRUE);
ONSIGNAL(onfpe, "Floating point exception", TRUE);
ONSIGNAL(onbus, "Bus Error", TRUE);
ONSIGNAL(onsegv, "Segmentation violation", TRUE);
ONSIGNAL(onxcpu, "Cpu limit exceeded", TRUE);
sighandler(signame, terminate)
char *signame;
Boolean terminate;
{
fflush(stdout);
fprintf(stderr, "\t=== %s signal trapped ===\n", signame);
fflush(stderr);
print_stats(stderr);
fflush(stderr);
fflush(stdout);
if (terminate == TRUE)
abort();
}